home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
accounts
/
npasswd_.000
/
npasswd_
/
npasswd_boulder
/
pw_passwd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-06
|
10KB
|
406 lines
/* -------------------------------------------------------------------- */
/* */
/* Author: Clyde Hoover */
/* Computation Center */
/* The University of Texas at Austin */
/* Austin, Texas 78712 */
/* clyde@emx.utexas.edu */
/* uunet!cs.utexas.edu!ut-emx!clyde */
/* */
/*This code may be distributed freely, provided this notice is retained. */
/* */
/* -------------------------------------------------------------------- */
/*
* pw_passwd - Routines for dealing with password files.
* Handles V7 / *.* BSD / Sys V format.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <pwd.h>
#include <fcntl.h>
#ifndef lint
static char sccsid[] = "@(#)pw_passwd.c 1.9 1/24/91 (cc.utexas.edu)";
#endif
#define SLOP 128 /* Size difference tolerated old <> new passwd file */
#ifdef SYSV
/*
* System V password aging stuff
*/
#define SEC_PER_WEEK ((long )24 * 7 * 60 * 60)
extern long a64l();
extern char *l64a();
static time_t pwage = 0,
maxpwtime = 0,
minpwtime = 0,
now;
#endif
typedef struct passwd passwd;
typedef struct passwd *passwdp;
static passwd theUser, /* The user to change */
Me; /* The user who invoked command */
static int myuid, /* Uid of program */
mytempfile = 0; /* Does PASSWD_TEMP belong to me? */
/*
* File names
*/
#ifndef PASSWD_FILE
#define PASSWD_FILE "/etc/passwd"
#endif
#ifndef PASSWD_SAVE
#define PASSWD_SAVE "/etc/opasswd"
#endif
#ifndef PASSWD_TEMP
#define PASSWD_TEMP "/etc/ptmp"
#endif
#define PASSWD_MODE 0644
#ifdef DEBUG
static char *passwdtemp = "./etc_ptmp",
*passwdfile = "./etc_passwd",
*savefile = "./etc_opasswd";
#else
static char *passwdtemp = PASSWD_TEMP,
*passwdfile = PASSWD_FILE,
*savefile = PASSWD_SAVE;
#endif
extern int errno;
char *getlogin(),
*crypt();
/*
* pw_initialize - set up
*/
pw_initialize()
{
passwdp me; /* Temp */
char *myname = getlogin(); /* Name of invoker */
#ifdef DEBUG
setpwfile(passwdfile);
#endif
myuid = getuid();
if (myname && *myname) {
if ((me = getpwnam(myname)) == NULL)
quit(1, "Cannot get user identification from name.\n");
} else {
if ((me = getpwuid(myuid)) == NULL)
quit(1, "Cannot get user identification from uid.\n");
}
_cppasswd(me, &Me);
return(1);
}
/*
* pw_getuserbyname - get password
*
* Returns 1 if passwd info found for <name>
* 0 otherwise
*/
pw_getuserbyname(name, passwdb)
char *name, /* User name */
*passwdb; /* Where to stuff password */
{
passwdp p; /* Temp */
if ((p = getpwnam(name)) == NULL)
return(0);
_cppasswd(p, &theUser);
(void) strcpy(passwdb, p->pw_passwd);
return(1);
}
/*
* pw_permission - check password change permission
*
* Returns 1 if password can be changed
* 0 if not
*/
pw_permission()
{
if (strcmp(Me.pw_name, theUser.pw_name) && myuid)
return(0);
/*
* Other checks can be put here to determine if the invoker should
* be allowed to change this password.
*/
#ifdef HAS_PW_AGE
if (theUser.pw_age) {
pwage = a64l(theUser.pw_age);
maxpwtime = pwage & 077;
minpwtime = (pwage >> 6) & 077;
pwage >>= 12;
(void) time(&now);
now /= SEC_PER_WEEK;
if (pwage <= now) {
if (myuid && (now < (pwage + minpwtime))) {
fprintf(stderr,
"Sorry: < %ld weeks since last change\n",
minpwtime);
return(0);
}
if ((minpwtime > maxpwtime) && myuid) {
fprintf(stderr,
"You may not change this password.\n");
return(0);
}
}
}
#endif
return(1);
}
/*
* pw_compare - compare old and new passwords
*
* Returns 1 if check = new, 0 if not
*/
pw_compare(current, check)
char *current, /* Current pw (encrypted) */
*check; /* check pw (plain) */
{
if (!*current)
return(0);
return(!strcmp(current, crypt(check, current)));
}
/*
* pw_check - sanity check password. Right now just calls
* the password check program
*
* Returns 1 if password is ok to use, 0 otherwise
*/
pw_check(newpw)
char *newpw; /* New password (plain) */
{
/* Put other administrative checks here */
return(checkpasswd(theUser.pw_uid, newpw));
}
/*
* pw_replace - replace password in passwd file
*/
pw_replace(newpwd, curpwd)
char *newpwd, /* New password (plain) */
*curpwd; /* Old password (plain) */
{
#ifdef SYSV
int (*sigint)(), /* Save SIGINT */
(*sigquit)(); /* Save SIGQUIT */
#else
long oldsigs, /* Signal mask save */
blocksigs = sigmask(SIGINT) | /* Signals to block */
sigmask(SIGQUIT) | /* while updating */
sigmask(SIGTSTP); /* password file */
#endif
passwdp px; /* Temp */
char salt[4]; /* Encryption salt */
FILE *tf; /* File ptr to new passwd file */
int fd; /* File desc. to new passwd file */
struct stat oldstat, /* Stat of current passwd file */
newstat; /* Stat of new passwd file */
/*
* Prepare password entry 'theUser' for replacement
*/
randomstring(salt, sizeof(salt));
theUser.pw_passwd = crypt(newpwd, salt);
#ifdef HAS_PW_AGE
/*
* Update password age field
*/
if (theUser.pw_age) {
if (maxpwtime == 0)
*theUser.pw_age = '\0';
else {
now = time((time_t *)0) / SEC_PER_WEEK;
pwage = maxpwtime
+ (minpwtime << 6)
+ (now << 12);
theUser.pw_age = l64a(pwage);
}
}
#endif
(void) umask(0);
(void) stat(passwdfile, &oldstat);
fd = open(passwdtemp, O_WRONLY|O_CREAT|O_EXCL, PASSWD_MODE);
if (fd < 0) {
if (errno == EEXIST)
quit(0, "Password file busy - try again.\n");
perror("Tempfile create");
quit(1, "Cannot create temp file.\n");
}
mytempfile = 1;
if ((tf = fdopen(fd, "w")) == NULL)
quit(1, "Cannot fdopen temp file.");
#ifdef SYSV
sigint = signal(SIGINT, SIG_IGN);
sigquit = signal(SIGQUIT, SIG_IGN);
#else
oldsigs = sigblock(blocksigs);
#endif
setpwent();
while ((px = getpwent()) != NULL) {
if (px->pw_name == 0 || px->pw_name[0] == 0) /* Sanity check */
continue;
if (strcmp(px->pw_name, theUser.pw_name) == 0)
px = &theUser;
(void) putpwent(px, tf);
}
endpwent();
(void) fflush(tf);
(void) fstat(fileno(tf), &newstat);
(void) fclose(tf);
/*
* Check if the new password file is complete. Since the encrypted
* password is of a fixed length, the new file should be roughly
* the same size as the old one.
*/
if (newstat.st_size < (oldstat.st_size - SLOP))
quit(1, "New password file appears to be incomplete - aborting.\n");
if (rename(passwdfile, savefile) < 0) {
perror("Password file save");
unlink(passwdtemp);
quit(1, "Can't save password file");
}
if (rename(passwdtemp, passwdfile) < 0) {
perror("Password file replace");
(void) unlink(passwdtemp);
(void) link(savefile, passwdfile);
quit(1, "Can't replace password file");
}
#ifdef NO_PASSWD_SAVE
(void) unlink(savefile);
#endif
#ifdef BSD4_3
updatedbm();
#endif
#ifdef SYSV
(void) signal(SIGINT, sigint);
(void) signal(SIGQUIT, sigquit);
#else
(void) sigsetmask(oldsigs);
#endif
}
/*
* pw_cleanup - clean up after myself
*/
pw_cleanup(code)
int code; /* 0 for normal, 1 for abort */ /*NOTUSED*/
{
if (mytempfile)
(void) unlink(passwdtemp);
}
/*
* _newstr - copy string into new storage
*/
static char *
_newstr(s)
char *s; /* String to copy */
{
register char *t; /* Temp */
char *malloc();
if (s == NULL)
return(0);
t = malloc(strlen(s) + 1);
if (t == NULL)
quit(1, "No memory.\n");
(void) strcpy(t, s);
return(t);
}
/*
* _cppasswd - copy a passwd structure
*/
static
_cppasswd(f,t)
passwdp f, /* From */
t; /* To */
{
*t = *f;
t->pw_name = _newstr(f->pw_name);
#ifdef HAS_PW_AGE
t->pw_age = _newstr(f->pw_age);
#endif
t->pw_passwd = _newstr(f->pw_passwd);
#ifdef HAS_PW_COMMENT
t->pw_comment = _newstr(f->pw_comment);
#endif
t->pw_gecos = _newstr(f->pw_gecos);
t->pw_dir = _newstr(f->pw_dir);
t->pw_shell = _newstr(f->pw_shell);
}
#ifdef BSD4_3
/*
* Update the hashed password data base
*/
#include <ndbm.h>
#define SCOPY(S) xp = (S); while (*cp++ = *xp++)
#define BCOPY(B) bcopy((char *)&(B), cp, sizeof(int)); cp += sizeof(int)
updatedbm()
{
DBM *pwd; /* DBM data base passwd */
register char *cp, /* Data storage pointer */
*xp; /* String copy pointer */
datum key, /* DBM key datum */
data; /* DBM data store datum */
char buf[512]; /* Data buffer */
pwd = dbm_open(passwdfile, O_RDWR, 0);
if (pwd == 0)
return;
cp = buf;
/* Pack passwd entry in the form expected by the getpw* routines */
SCOPY(theUser.pw_name);
SCOPY(theUser.pw_passwd);
BCOPY(theUser.pw_uid);
BCOPY(theUser.pw_gid);
BCOPY(theUser.pw_quota);
SCOPY(theUser.pw_comment);
SCOPY(theUser.pw_gecos);
SCOPY(theUser.pw_dir);
SCOPY(theUser.pw_shell);
data.dptr = buf;
data.dsize = cp - buf;
key.dptr = theUser.pw_name;
key.dsize = strlen(theUser.pw_name);
if (dbm_store(pwd, key, data, DBM_REPLACE) < 0) {
perror("dbm_store (name)");
quit(1, "Can't store passwd entry (name key).\n");
}
key.dptr = (char *)&theUser.pw_uid;
key.dsize = sizeof (int);
if (dbm_store(pwd, key, data, DBM_REPLACE) < 0) {
perror("dbm_store (uid)");
quit(1, "Can't store passwd entry (uid key).\n");
}
dbm_close(pwd);
}
#endif